#include <dshow.h>
#include "AudioPlayCmd.h"
#include "mzuser.h"
CAudioPlayCmd::CAudioPlayCmd()
{
	InitializeCriticalSection(&m_csCtrl);
	m_pmModePlay = MODE_PLAY_ALL;
}

CAudioPlayCmd::~CAudioPlayCmd()
{
	DeleteCriticalSection(&m_csCtrl);

}

HRESULT CAudioPlayCmd::OpenClip(LPTSTR szFile)
{
	EnterCriticalSection (&m_csCtrl);
	static	int	nPlay = 0;
	HRESULT		hr;

	IMediaControl	*pMC;
	IMediaEventEx	*pME;
	IGraphBuilder	*pGB;
	IVideoWindow 	*pVW;
	IMediaSeeking	*pMS;
	LONG			lWidth = 0;
	LONG			lHeight = 0;

	if (!szFile)
	{
		LeaveCriticalSection (&m_csCtrl);
		return E_POINTER;
	}

	// Get the interface for DirectShow's GraphBuilder
	hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, reinterpret_cast<PVOID *>( &m_pGB ));
	pGB = reinterpret_cast<IGraphBuilder *>( m_pGB );
 
	if(SUCCEEDED(hr))
	{		

		// Have the graph builder construct its appropriate graph automatically
		HRESULT TEM = pGB->RenderFile(szFile, NULL);
		if (FAILED(TEM))
		{
			pGB->Release();
			pGB = NULL;
			LeaveCriticalSection (&m_csCtrl);
			return TEM;		
		}

		// QueryInterface for DirectShow interfaces
		if( FAILED(pGB->QueryInterface(IID_IMediaControl, reinterpret_cast<PVOID *>( &m_pMC ))) )
		{
			CloseInterfaces();
			return S_FALSE;
		}
		if( FAILED(pGB->QueryInterface(IID_IMediaEventEx, reinterpret_cast<PVOID *>( &m_pME ))) )
		{
			CloseInterfaces();
			return S_FALSE;
		}
		if( FAILED(pGB->QueryInterface(IID_IMediaSeeking, reinterpret_cast<PVOID *>( &m_pMS ))) )
		{
			CloseInterfaces();
			return S_FALSE;
		}
		//      m_pGB->QueryInterface(IID_IMediaPosition, (void **)&m_pMP);
		// Query for audio interfaces, which may not be relevant for video-only files
		if( FAILED(pGB->QueryInterface(IID_IBasicAudio, reinterpret_cast<PVOID *>( &m_pBA ))) )
		{
			CloseInterfaces();
			return S_FALSE;
		}

		if( SUCCEEDED(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)) )
		{
			pVW->put_Width( 0 );
			pVW->put_Height( 0 );	
			pVW->put_AutoShow( OAFALSE );
		}
		else
		{
			CloseInterfaces();
			return S_FALSE;
		}

		// Have the graph signal event via window callbacks for performance
//jdhuang 20120819
		pME = reinterpret_cast<IMediaEventEx *>( m_pME );
//		pME->SetNotifyWindow((OAHWND)m_hParent, MGSID_GRAPHNOTIFY, 0);
		pME->SetNotifyWindow((OAHWND)m_hParent, WM_GRAPH_NOTIFY, 0);

		try
		{
//jdhuang 20120820
			LONGLONG pos = 1E7;
//			LONGLONG pos = 100;
			//Play the media file
			pMC = reinterpret_cast<IMediaControl *>( m_pMC );		
			pMS = reinterpret_cast<IMediaSeeking *>( m_pMS );		
			hr = pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
			hr = pMC->Run();
			if (SUCCEEDED(hr))
			{			
				pVW->put_Visible( OAFALSE  );				
//jdhuang 20120820
//				m_psCurrent = psMP3RUNNING;
				m_psStatusPlay = STATUS_PLAY;
			}
			else
			{
				LeaveCriticalSection (&m_csCtrl);
				return hr;
			}
			pVW->Release();
			pVW = NULL;
		}
		catch( ... )
		{
			LeaveCriticalSection (&m_csCtrl);
			return S_FALSE;
		}
	}

	nPlay = 0;

//jdhuang 20120819
//	InitAudioPlayVolume();
	SetTimer(m_hParent, MZ_PLAYTIMER_TIME, 500, NULL);
	LeaveCriticalSection (&m_csCtrl);
	return hr;
}

void CAudioPlayCmd::CloseClip()
{
	EnterCriticalSection (&m_csCtrl);
	//	SaveAudioPlayVolume();

	// Stop media playback
	if(m_psStatusPlay != STATUS_STOP)
	{
		if(m_pMC) 
		{
			IMediaControl	*pMC = reinterpret_cast<IMediaControl *>( m_pMC );
			pMC->StopWhenReady();
		}

		CloseInterfaces();
		KillTimer(m_hParent, MZ_PLAYTIMER_TIME);
	}

	// No current media state
//jdhuang 20120820
//	m_psCurrent = psMP3INIT;
	m_psStatusPlay = STATUS_STOP;

	LeaveCriticalSection (&m_csCtrl);
}
BOOL CAudioPlayCmd::PauseClip()
{
	EnterCriticalSection (&m_csCtrl);
	if (!m_pMC)
	{
		LeaveCriticalSection (&m_csCtrl);
		return FALSE;
	}
	IMediaControl	*pMC = reinterpret_cast<IMediaControl *>( m_pMC );

	// Toggle play/pause behavior
//jdhuang 20120820
/*	if((m_psCurrent == psMP3PAUSED) || (m_psCurrent == psMP3STOPPED))
	{
		if (SUCCEEDED(pMC->Run()))
		{
			m_psCurrent = psMP3RUNNING;
		}
	}
	else
	{
		if (SUCCEEDED(pMC->Pause()))
		{
			m_psCurrent = psMP3PAUSED;
		}
	}
*/

	switch(m_psStatusPlay)
	{
	case STATUS_PAUSE:
		{
			if (SUCCEEDED(pMC->Run()))
			{
				m_psStatusPlay = STATUS_PLAY;
			}
			break;
		}
	case STATUS_PLAY:
		if (SUCCEEDED(pMC->Pause()))
		{
			m_psStatusPlay = STATUS_PAUSE;
		}
		break;
	}
	LeaveCriticalSection (&m_csCtrl);
	return TRUE;
}

void CAudioPlayCmd::StopClip()
{
//jdhuang 20120822
#if 0
	EnterCriticalSection (&m_csCtrl);
	if ((!m_pMC) || (!m_pMS))
	{
		LeaveCriticalSection (&m_csCtrl);
		return;
	}

	HRESULT hr;
	IMediaControl	*pMC = reinterpret_cast<IMediaControl *>( m_pMC );
	IMediaSeeking	*pMS = reinterpret_cast<IMediaSeeking *>( m_pMS );

	// Stop and reset postion to beginning
	if((m_psCurrent == psMP3PAUSED) || (m_psCurrent == psMP3RUNNING))
	{
		LONGLONG pos = 0;

		if (SUCCEEDED(pMC->Stop()))
			m_psCurrent = psMP3STOPPED;

		// Seek to the beginning
		hr = pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning ,
			NULL, AM_SEEKING_NoPositioning);

		/*
		// Display the first frame to indicate the reset condition
		hr = pMC->Pause();
		*/
	}
	LeaveCriticalSection (&m_csCtrl);
#endif
}
void CAudioPlayCmd::CloseInterfaces()
{
	// Release and zero DirectShow interfaces
	if(m_pME)
	{
		IMediaEventEx	*pME = reinterpret_cast<IMediaEventEx *>(m_pME);
		pME->SetNotifyWindow((OAHWND)NULL, 0, 0);
		pME->Release();	
		pME = NULL;	
		m_pME = NULL;
	}
	if(m_pMS)
	{
		IMediaSeeking	*pMS = reinterpret_cast<IMediaSeeking *>(m_pMS);
		pMS->Release();	
		pMS = NULL;	
		m_pMS = NULL;
	}
	if(m_pMC)
	{
		IMediaControl	*pMC = reinterpret_cast<IMediaControl *>(m_pMC);
		pMC->Release();	
		pMC = NULL;	
		m_pMC = NULL;
	}
	if(m_pBA)
	{
		IBasicAudio		*pBA = reinterpret_cast<IBasicAudio*>( m_pBA );
		pBA->Release();	
		pBA = NULL;
		m_pBA = NULL;
	}
	if(m_pGB)
	{	
		IGraphBuilder	*pGB = reinterpret_cast<IGraphBuilder *>( m_pGB );
		pGB->Release();	
		pGB = NULL;	
		m_pGB = NULL;
	}
}

long CAudioPlayCmd::GetCurPosTime()
{
	if(m_pMS == NULL) return 0;
	IMediaSeeking	*pMS = reinterpret_cast<IMediaSeeking *>( m_pMS );

	LONGLONG pos;
	pMS->GetPositions(&pos,NULL);
//jdhuang 20120820
	return( pos / 1E7 );
}
long CAudioPlayCmd::GetDurationTime()
{
	if(m_pMS == NULL) return 0;
	IMediaSeeking	*pMS = reinterpret_cast<IMediaSeeking *>( m_pMS );

	LONGLONG pos;
	pMS->GetDuration(&pos);
//jdhuang 20120820
	return( pos / 1E7 );
//	return( pos / 100 );
}

void CAudioPlayCmd::SetPosTime(int p)
{
//	if(!(m_psCurrent == psMP3RUNNING || m_psCurrent ==psMP3PAUSED))	return ;
	if((m_psStatusPlay == STATUS_PLAY) || (m_psStatusPlay == STATUS_PAUSE))
	{
		LONGLONG pos,lTotal;
		HRESULT hr=S_OK;
		if(!m_pMS)
			return;
		IMediaSeeking	*pMS = reinterpret_cast<IMediaSeeking *>( m_pMS );

		hr = pMS->GetDuration(&lTotal);

		pos = p * lTotal / 100; 

		hr = pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
	}
}

HRESULT CAudioPlayCmd::HandleGraphEvent()
{
	LONG evCode, evParam1, evParam2;
	HRESULT hr=S_OK;

	if (!m_pME)  return S_OK;
	IMediaEventEx	*pME = reinterpret_cast< IMediaEventEx *>( m_pME );

	// Process all queued events
	while(SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR *) &evParam1, (LONG_PTR *) &evParam2, 0)))
	{		
		switch(evCode)
		{	
		case EC_STREAM_ERROR_STOPPED:
			MessageBox(NULL, L"EC_STREAM_ERROR_STOPPED", L"Event", MB_OK);
			break;

		case EC_SHUTTING_DOWN:
			MessageBox(NULL, L"EC_SHUTTING_DOWN", L"Event", MB_OK);
			break;

		case EC_STREAM_CONTROL_STOPPED:
			MessageBox(NULL, L"EC_stat", L"Event", MB_OK);
			break;

		case EC_ERRORABORT:
//			RETAILMSG(MUSIC_PLAYER_DEBUG, (TEXT("EC_ERRORABORT Occour\n")));
#ifdef _DEBUG
			printf("EC_ERRORABORT\r\n");
#endif
//			SendMessage(m_hParent, WM_COMMAND, ID_EC_ERRORABORT, NULL);
			break;

		case EC_USERABORT:
//			RETAILMSG(MUSIC_PLAYER_DEBUG, (TEXT("EC_USERABORT Occour\n")));
#ifdef _DEBUG
			printf("EC_USERABORT\r\n");
#endif
			break;

		case EC_COMPLETE:
//jdhuang 20120820
/*
			if(m_pMC && m_pMS)
			{
				IMediaControl	*pMC = (IMediaControl *)m_pMC;
				IMediaSeeking	*pMS = (IMediaSeeking *)m_pMS;

//				RETAILMSG(MUSIC_PLAYER_DEBUG, (TEXT("EC_COMPLETE Occour\n")));
				//					SaveAudioPlayVolume();

				LONGLONG pos=0;
				HANDLE hAudioPauseEvent = OpenEvent(EVENT_ALL_ACCESS, false, _T("bAudioNavi MISS"));
				if(hAudioPauseEvent) SetEvent(hAudioPauseEvent);
				if(hAudioPauseEvent) CloseHandle(hAudioPauseEvent);
				// Reset to first frame of movie
				hr = pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
				hr = pMC->Stop();
				m_psCurrent = psMP3STOPPED;

//				PostMessage(m_hParent, WM_COMMAND, ID_EC_COMPLETE, NULL);
			}
*/
			CloseClip();
			if(m_pmModePlay == MODE_PLAY_ALL)
			{
				SendMessage(m_hParent, MZ_WM_COMMAND, (WPARAM)3202, (LPARAM)0);//Command Next
			}
			break;
		}

		// Free memory associated with callback, since we're not using it
		hr = pME->FreeEventParams(evCode, evParam1, evParam2);
	}
	return hr;
}

void CAudioPlayCmd::SetParentHandle(HWND hWnd)
{
	m_hParent = hWnd;
}
void CAudioPlayCmd::OnFilePlay(TCHAR *pStrFullFileName)
{
	switch(m_psStatusPlay)
	{
	case STATUS_STOP:
		OpenClip(pStrFullFileName);
		break;
	case STATUS_PLAY:
		PauseClip();
		break;
	case STATUS_PAUSE:
		PauseClip();
		break;

	}

}
void CAudioPlayCmd::OnFileStop()
{
	CloseClip();
}
void CAudioPlayCmd::OnFilePause()
{
}
void CAudioPlayCmd::OnFileNext(TCHAR *pStrFullFileName)
{
	switch(m_psStatusPlay)
	{
	case STATUS_STOP:
		OpenClip(pStrFullFileName);
		break;
	case STATUS_PLAY:
	case STATUS_PAUSE:
		CloseClip();
		OpenClip(pStrFullFileName);
		break;
	}
}
void CAudioPlayCmd::OnFilePrev(TCHAR *pStrFullFileName)
{
	switch(m_psStatusPlay)
	{
	case STATUS_STOP:
		OpenClip(pStrFullFileName);
		break;
	case STATUS_PLAY:
	case STATUS_PAUSE:
		CloseClip();
		OpenClip(pStrFullFileName);
		break;
	}
}